# coding=utf-8
# Author: Heanny Liu
# Date: 2016-10-17
# Version: 2.6.170719
# RelyOn: paramiko,tqdm

import paramiko
import os, sys, time, re
from tqdm import tqdm

# kill进程问题
_print = print


def print(msg):
	_print('{} >> {}'.format(time.strftime('%Y-%m-%d %H:%M:%S'), msg))


class pBar():
	def __init__(self):
		self.all = 0
		self.aa = 0
		self.pbar = None

	def _update(self, a, b):
		if self.all == 0:
			self.all = b
			self.pbar = tqdm(total=self.all, unit='Byte',
			                 desc='{} >> update'.format(time.strftime('%Y-%m-%d %H:%M:%S')))
		# print(a,b)
		self.pbar.update(a - self.aa)
		self.aa = a
		if a == b:
			self.pbar.close()
	def _close(self):
		self.pbar.close()


# 服务器实体类
class Server():
	def __init__(self, server):
		self.host = server[0]
		self.port = 22
		self.user = server[1]
		self.password = server[2]
		paramiko.util.log_to_file('paramiko.log')
		self.ssh = paramiko.SSHClient()
		# 允许将信任的主机自动加入到host_allow 列表，此方法必须放在connect方法的前面
		self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
		if len(server) == 4:
			'''通过密钥登录。server：host user key'spwd key'spath'''
			self.pkey = server[3]
			self.key = paramiko.RSAKey.from_private_key_file(self.pkey, password=self.password)
		else:
			'''通过密码登录。server：host user pwd'''
			self.key = 0
		self.hcbc_path = "/usr/local/hcbc"
		self.hcbc_package = "hcbc-0.0.1-SNAPSHOT.jar"
		self.t = ""

	# 通过SSH连接服务器
	def _connect_server(self):
		print("Connect Server %s ..." % (self.host))
		try:
			if self.key == 0:
				'''通过密码连接服务器'''
				self.ssh.connect(self.host, self.port, self.user, self.password, timeout=50)
			else:
				'''通过密钥链接服务器'''
				self.ssh.connect(self.host, self.port, self.user, pkey=self.key, timeout=50)
			print("Connect Success !")
			self.t = paramiko.SFTPClient.from_transport(self.ssh.get_transport())
			return True
		except Exception as e:
			print("Connect {} Fail ! {}".format(self.host, e))
			return False

	def _sftp(self):
		self.sftp = self.ssh.open_sftp()
		print("SFTP is Open !")

	def _close(self):
		self.ssh.close()
		print("SSH is Closed !")

	def _killJar(self):
		reData = self._command("bash -lc 'ps -aux | grep \'java -jar {}\''".format(self.hcbc_package))
		for data in reData:
			print(data.replace('\n', ''))
			dId = data.replace('\n', '').replace('root', '')
			out = re.sub(r"\s{2,}", " ", dId).lstrip().split(' ')[0]
			self._command('kill {}'.format(int(out)))
		self._command('rm -rf /user/local/hcbc/{}'.format(self.hcbc_package))

		return True

	def _command(self, cmd):
		stdin, stdout, stderr = self.ssh.exec_command(cmd)
		return stdout.readlines()

	def _check_hcbc_path(self):
		reData = self._command('find /usr/local/ -name "hcbc" -type d'.format(self.hcbc_path))
		if len(reData) == 0:
			self._command('mkdir /usr/local/hcbc')
			print('mkdir hcbc success')
		return True

	def _update_hcbc(self):
		local_file_path = os.path.dirname(os.path.realpath(__file__)) + "/" + self.hcbc_package
		remote_file_path = self.hcbc_path + "/" + self.hcbc_package
		print("Start Upload %s to %s" % (local_file_path, remote_file_path))
		p = pBar()
		self.sftp.put(local_file_path, remote_file_path, callback=p._update)
		p._close()
		_print('\n{} >> Upload Success !'.format(time.strftime('%Y-%m-%d %H:%M:%S')))
		return True

	def _startNewJar(self):
		com = 'nohup java -jar /usr/local/hcbc/hcbc-0.0.1-SNAPSHOT.jar > /tmp/1 2>&1 & \r\n'.format(self.hcbc_package)
		reD = self._command("bash -lc '{}'".format(com))
		print(reD)
		return True


def read_server_info(serverFile):
	server_list = []
	'''读取servers.txt的文件获取服务器相关信息'''
	file = open(serverFile)
	lines = file.readlines()
	for line in lines:
		server_list.append(line.replace('\n', '').split(' '))
	file.close()
	return server_list


def view_bar(num, total):
	rate = num / total
	rate_num = int(rate * 100)
	v_num = int(rate * 50)
	r = '\r[%s%s]%d%%' % (">" * v_num, " " * (50 - v_num), rate_num,)
	sys.stdout.write(r)
	sys.stdout.flush()


def main():
	serverFile = "servers.txt"
	for server in read_server_info(serverFile):
		pattern = re.compile(r'#')
		if re.match(pattern, server[0]):
			print('{} is the cover ignore.'.format(server[0]))
		else:
			Link = Server(server)
			if Link._connect_server():
				Link._check_hcbc_path()
				Link._killJar()
				Link._sftp()
				Link._update_hcbc()
			Link._startNewJar()
			Link._close()


# 执行主进程
if __name__ == "__main__":
	main()
